package dan.common
import chisel3._
import chisel3.util._
import dan.common.Consts.UOP_BITS
import dan.common.Consts.IQT_BITS
import dan.common.Consts.FU_BITS
import dan.common.Consts.REGT_BITS
import dan.common.Consts.IMM_X
import dan.common.Consts.UOP_INVTLB
import dan.common.Consts.BR_BITS
import dan.common.Consts.OP1T_BITS
import dan.common.Consts.OP2T_BITS
import dan.common.Consts.IMMT_BITS
import dan.common.Consts.FU_CNT
import dan.backend.AluFuncCode
import dan.common.Consts.CSR_BITS
import dan.common.Consts.REGT_GPR
import dan.common.Consts.UOP_NOP
import dan.common.Consts.FPGA_RUN

class CtrlSignal extends CoreBundle{
    val brType: UInt = UInt(BR_BITS.W)
    val oprand1Type: UInt = UInt(OP1T_BITS.W)
    val oprand2Type: UInt = UInt(OP2T_BITS.W)
    val immType: UInt = UInt(IMMT_BITS.W)
    val funcCode: UInt = UInt(new AluFuncCode().SZ_ALU_FN.W)
    val csrCmd: UInt = UInt(CSR_BITS.W)
    val isLd: Bool = Bool()
    // 见Consts
    val isStA: Bool = Bool()
    val isStD: Bool = Bool()
}

class UOp extends CoreBundle{
    // TODO
    val useStQ: Bool = Bool()
    val isLL: Bool = Bool()
    val isSC: Bool = Bool()

    val ftqSize: Int = frontendParam.ftqSize
    val fetchBytes: Int = frontendParam.fetchBytes
    val robBits: Int = robParam.robIdxBits
    val ldqBits: Int = lsuParam.ldqIdxBits
    val stqBits: Int = lsuParam.stqIdxBits
    // 一个取值pack中的低位地址
    val pcLow: UInt = UInt(log2Ceil(fetchBytes).W)
    val instr: UInt = UInt(instrBits.W)
    val uopType: UInt = UInt(UOP_BITS.W)
    val iqType: UInt = UInt(IQT_BITS.W)
    val fuType: UInt = UInt(FU_BITS.W)
    val ftqIdx: UInt = UInt(log2Ceil(frontendParam.ftqSize).W)
    val isBr: Bool = Bool()
    val isJal: Bool = Bool()
    val isJalr: Bool =  Bool()
    val taken: Bool = Bool()
    // 当前微操作依赖的分支指令
    val brMask: UInt = UInt(maxBrNum.W)
    val brTag: UInt = UInt(brTagBits.W)

    val archDst: UInt = UInt(archRegBits.W)
    val archDstValid: Bool = Bool()
    val archDstType: UInt = UInt(REGT_BITS.W)
    val archOprand1: UInt = UInt(archRegBits.W)
    val archOp1Type: UInt = UInt(REGT_BITS.W)
    val archOprand2: UInt = UInt(archRegBits.W)
    val archOp2Type: UInt = UInt(REGT_BITS.W)
    val physDst: UInt = UInt(physRegBits.W)
    val physOprand1: UInt = UInt(physRegBits.W)
    val physOprand2: UInt = UInt(physRegBits.W)
    // 上一个物理寄存器，当前指令提交后可释放
    val stalePhysDst: UInt = UInt(physRegBits.W)
    val bypassable: Bool =  Bool()
    val formatImm: UInt = UInt(26.W)
    val robIdx: UInt = UInt(robBits.W)
    val ldqIdx: UInt = UInt(ldqBits.W)
    val stqIdx: UInt = UInt(stqBits.W)
    // 处于发射窗口中的状态
    val issueWinState: UInt = UInt(2.W)
    // 操作数位于错误路径上
    val op1Poisoned: Bool = Bool()
    val op2Poisoned: Bool = Bool()
    val op1Busy: Bool = Bool()
    val op2Busy: Bool = Bool()
    val expValid: Bool = Bool()
    val expCause: UInt = UInt(ExpCode.microExpBits.W)
    // 是否需要将导致访存异常的地址写入CSR寄存器
    val vaWrEnable: Bool = Bool()
    val ctrl = new CtrlSignal()
    // 内存相关信息
    val tlbOp: UInt = UInt(5.W)
    val useLdQ: Bool = Bool()
    val memSize: UInt = UInt(memWidth.W)
    // 对于加载操作，是进行有符号扩展还是无符号扩展
    val memSigned: Bool = Bool()
    val isDbar: Bool = Bool()
    val isIbar: Bool = Bool()
    // 需要等待流水线清空
    val isUnique: Bool = Bool()
    val flushIfCommit: Bool = Bool()

    def needBrTag: Bool = isBr || isJalr
    def regWrEnable: Bool = archDstType === REGT_GPR
    def fuTypeEqual(code: UInt): Bool = (code & fuType) =/= 0.U
    def isNOP: Bool = uopType === UOP_NOP

    val debugInstr: UInt = if(!FPGA_RUN) UInt(instrBits.W) else null
    val debugPC: UInt = if(!FPGA_RUN) UInt(vaBits.W) else null
    val debugMispredict: Bool = if(!FPGA_RUN) Bool() else null
    val debugLdUncache: Bool = if(!FPGA_RUN) Bool() else null
}

trait HasUOp extends Bundle {
    val uop = new UOp
}


